/*
 * @Descripttion: GGB
 * @version: 1.0
 * @Author: GGB
 * @Date: 2022-01-30 13:40:46
 * @LastEditors: GGB
 * @LastEditTime: 2022-02-01 18:23:40
 */
const qiniu = require('qiniu')
const axios = require('axios')
const fs=require('fs')
class QiniuManager {
    constructor(accessKey, secretKey, bucket) {
        this.mac = new qiniu.auth.digest.Mac(accessKey, secretKey);
        this.bucket = bucket
        this.config = new qiniu.conf.Config();
        this.config.zone = qiniu.zone.Zone_z0;
        this.bucketManager = new qiniu.rs.BucketManager(this.mac, this.config);
    }
    // 文件上传
    uploadFile(key, localFilePath) {
        const options = {
            scope: this.bucket + ':' + key,
        };
        const putPolicy = new qiniu.rs.PutPolicy(options);
        const uploadToken = putPolicy.uploadToken(this.mac);

        const formUploader = new qiniu.form_up.FormUploader(this.config);
        const putExtra = new qiniu.form_up.PutExtra();
        return new Promise((resolve, reject) => {
            // // 文件上传
            formUploader.putFile(uploadToken, key, localFilePath, putExtra,this._handleCallback(resolve,reject));
        })

    }
    // 获取bucket空间域名
    getBucketDomain() { 
        const reqURL = `http://uc.qbox.me/v2/domains?tbl=${this.bucket}`
        const digest = qiniu.util.generateAccessToken(this.mac, reqURL)
        return new Promise((resolve, reject) => { 
            qiniu.rpc.postWithoutForm(reqURL,digest,this._handleCallback(resolve, reject))
        })
    }
    /**
     * 生成下载链接
     * @param {*} key 
     * @returns 
     */
    generateDownloadLink(key) { 
        const domainPromise = this.publicBucketDomain
            ? Promise.resolve([this.publicBucketDomain])
            : this.getBucketDomain()
        return domainPromise.then(data => {
            if (Array.isArray(data) && data.length > 0) {
                const pattern = /^https?/
                this.publicBucketDomain = pattern.test(data[0])
                    ? data[0] : `http://${data[0]}`
                return this.bucketManager.publicDownloadUrl(this.publicBucketDomain, key)
            } else { 
                throw Error("域名已过期")
            }
        })
    }

    getStat(key) {
        console.log(key)
        return new Promise((resolve, reject) => { 
            this.bucketManager.stat(this.bucket,key,this._handleCallback(resolve, reject))
        })
     }

    /**
     * 下载文件
     * @param {*} key 
     * @param {*} downloadPath 
     * @returns 
     */
    downloadFile(key, downloadPath) { 
        // step 1 get the download link
        // step 2 send the request to download link return a readable stream
        // step 3 create a writable stream and pipe to it
        // step 4 return a promise based result
      return  this.generateDownloadLink(key).then(link => { 
            const timestamp = new Date().getTime()
            const url = `${link}?timestamp=${timestamp}`
            return axios({
                url,
                methods: 'GET',
                responseType: 'stream',
                headers:{'Cache-Control':'no-cache'}
            })
        }).then(response => { 
            const writer = fs.createWriteStream(downloadPath)
            response.data.pipe(writer)
            return new Promise((resolve, reject) => { 
                writer.on('finish', resolve)
                writer.on('error',reject)
            })
        }).catch(err => { 
            // 捕获 axios的错误
            return Promise.reject({err:err.response})
        })
    }
    // 删除七牛云的文件
    deleteFile(key) {
        return new Promise((resolve, reject) => {
            this.bucketManager.delete(this.bucket, key,this._handleCallback(resolve,reject));
        })
    }
    /**
     * 重命名文件
     * @param {*} key 
     * @param {*} targetKey 
     * @returns 
     */
    renameFile(key,targetKey) { 
        return new Promise((resolve, reject) => {
            this.bucketManager.move(this.bucket, key, this.bucket, targetKey, {},this._handleCallback(resolve,reject));
        })
    }
    /**
     * 获取指定文件列表
     * @param {*} bucket 
     */
    getFileList() { 
        return new Promise((resolve, reject) => { 
            const options = {
                limit:1000000
            }
            this.bucketManager.listPrefix(this.bucket,options,this._handleCallback(resolve,reject))
        })
    }

    /**
     * 高阶回调函数 =>(respErr,respBody, respInfo)(resolve, reject)
     * @param {*} resolve 
     * @param {*} reject 
     * @returns 
     */

    _handleCallback(resolve, reject) { 
        return (respErr,respBody, respInfo) => { 
            if (respErr) {
                throw respErr;
            }
            if (respInfo.statusCode == 200) {
                resolve(respBody)
            } else {
                console.log(respInfo.statusCode);
                console.log(respBody);
                reject({
                    statusCode: respInfo.statusCode,
                    body: respBody
                })
            }
        }
    }
}

module.exports = QiniuManager